/*
 * HashTable.cpp
 *
 *  Created on: Nov 1, 2013
 *      Author: SG0214746
 */

#include "HashTable.h"
#include "../../log/Logger.h"
#include "../../utils/Utils.h"

HashTable::HashTable() {
	table.push_back(0);
}

HashTable::~HashTable() {
}

void HashTable::set(BigInt beg, BigInt end, BigInt value) {
	for (BigInt x = beg; x <= end; x++)
		table[x] = value;
	save();
	Logger::getInstance().debug("HashTable: valores seteados a " + toString());
}

void HashTable::setCircular(BigInt beg, BigInt jump, BigInt value) {
	BigInt x = beg;
	do {
		table[x] = value;
		x += jump;
		if (x >= table.size()) {
			x -= table.size();
		}
	} while (x != beg);
	save();
	Logger::getInstance().debug("HashTable: referencias cambiadas a " + toString());
}

void HashTable::replace(BigInt previous, BigInt value) {
	for (Iterator it = table.begin(); it != table.end(); ++it) {
		if (*it == previous) {
			*it = value;
		}
	}
	save();
}

void HashTable::duplicate() {
	table.insert(table.begin() + table.size(), table.begin(), table.end());
	save();
	Logger::getInstance().debug("HashTable: duplicada a " + toString());
}

bool HashTable::reduce() {
	BigInt half = table.size()/2;
	for (BigInt x = 0; x < half; ++x) {
		if (table[x] != table[x + half]) {
			return false;
		}
	}
	table.resize(half);
	save();
	Logger::getInstance().debug("HashTable: reducida a " + toString());
	return true;
}

BigInt HashTable::get(BigInt index) const {
	while (index >= table.size()) {
		index -= table.size();
	}
	return table[index];
}

BigInt HashTable::size() const {
	return table.size();
}

void HashTable::save() {
	getDescriptor().seekp(0, std::fstream::beg);
	getDescriptor().write((char*)&table[0], table.size()*sizeof(BigInt));
	getDescriptor().flush();
}

void HashTable::load() {
	getDescriptor().seekg(0, std::istream::end);
	BigInt fileSize = getDescriptor().tellg();
	table.resize(fileSize/sizeof(BigInt));
	getDescriptor().seekg(0, std::istream::beg);
	getDescriptor().read((char*)&table[0], fileSize);
	Logger::getInstance().debug("HashTable: leido " + toString());
}

String HashTable::toString() const {
	std::string aux;
	for (ConstIterator it = table.begin(); it != table.end(); ++it) {
		aux += "[" + Utils::toString(*it) + "]";
	}
	return aux;
}
